home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / ddx / dec / qdss / qdspans.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-26  |  22.3 KB  |  831 lines

  1. /***********************************************************
  2. Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
  3. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Digital or MIT not be
  12. used in advertising or publicity pertaining to distribution of the
  13. software without specific, written prior permission.  
  14.  
  15. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  16. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  17. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  18. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  19. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  20. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21. SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. extern int PixmapUseOffscreen;
  26. #include "scrnintstr.h"
  27.  
  28. #include "pixmapstr.h"
  29.  
  30. #include <sys/types.h>
  31.  
  32. #include "X.h"
  33. #include "windowstr.h"
  34. #include "regionstr.h"
  35. #include "gcstruct.h"
  36. #include "dixstruct.h"
  37.  
  38. #include "Xproto.h"
  39. #include "Xprotostr.h"
  40. #include "mi.h"
  41. #include "Xmd.h"
  42. #include "servermd.h"
  43.  
  44. /*
  45.  * driver headers
  46.  */
  47. #include "Ultrix2.0inc.h"
  48. #include <vaxuba/qduser.h>
  49. #include <vaxuba/qdioctl.h>
  50. #include <vaxuba/qdreg.h>
  51.  
  52. #include "qd.h"
  53. #include "qdgc.h"
  54.  
  55. #include "qdprocs.h"
  56.  
  57. /*
  58.  * used as procedure vector when drawable is an undrawable window
  59.  */
  60. void
  61. qdFSUndrawable()
  62. {
  63. }
  64.  
  65. #define    PIXDEPTH(x)    ((x->drawable).depth)
  66. /* ZCOPY - XXX replaced by does-everything function qddopixel! */
  67. #if NPLANES==24
  68. # define ZCOPY(s,d,sw,dw) \
  69.        {*((unsigned char *) d) = *((unsigned char *) s); \
  70.     *(((unsigned char *) d)+dw) = *(((unsigned char *) s)+sw); \
  71.     *(((unsigned char *) d)+2*(dw)) = *(((unsigned char *) s)+2*(sw));}
  72. #else    /* NPLANES == 8 */
  73. # define ZCOPY(s,d,sw,dw) \
  74.        {*((unsigned char *) d) = *((unsigned char *) s);}
  75. #endif
  76.  
  77. #if NPLANES==24
  78. #define DOPIXEL(psrc, dst, pGC, delta) qddopixel(psrc, dst, pGC, delta)
  79. #else
  80. #define DOPIXEL(psrc, dst, pGC, delta) qddopixel(psrc, dst, pGC)
  81. #endif
  82.  
  83.  
  84. #define u_char    unsigned char
  85.  
  86. /*
  87.  * GetSpans -- for each span, gets bits from drawable starting at ppt[i]
  88.  * and continuing for pwidth[i] bits
  89.  * Each scanline returned will be server scanline padded, i.e., it will come
  90.  * out to an integral number of longwords.
  91.  */
  92. /*
  93.  * Currently, the caller does an Xfree of the returned value.
  94.  *
  95.  * If Drawable is the screen
  96.  *    hand the bytes back a pixel at a time.
  97.  * If Drawable is a pixmap
  98.  *    hand the bytes back a pixel at a time.
  99.  */
  100.  
  101. extern    int Nentries;
  102. extern    int Nplanes;
  103. #if NPLANES==24
  104. extern    int Nchannels;
  105. #else
  106. #define Nchannels 1
  107. #endif
  108. extern unsigned int Allplanes;
  109.  
  110. #ifdef X11R4
  111. /*
  112.  * In R4, we change the interface slightly for GetSpans when pDrawable
  113.  * is a Pixmap: pDrawable->{x,y} must have been pre-addes to the ppt
  114.  * coordinates. For off-screen Pixmaps, this means they have absolute
  115.  * GPX-relative coordinates, which is what we want anyway.
  116.  * This convention is useful, because the mi routines usually add
  117.  * in pDrawable->{x,y} before calling GetSpans. The exception is
  118.  * miPushPixels (since it "knows" that the mask is a Bitmap); we have
  119.  * to be sure it is only called when mask->drawable->{x,y} are both 0.
  120.  */
  121. #endif
  122.  
  123. #ifdef X11R4
  124. void
  125. qdGetSpans( pDrawable, wMax, ppt, pwidth, nspans,pdstStart)
  126. #else
  127. unsigned int *
  128. qdGetSpans( pDrawable, wMax, ppt, pwidth, nspans)
  129. #endif
  130.     DrawablePtr        pDrawable;    /* drawable from which to get bits */
  131.     int            wMax;        /* largest value of all *pwidths */
  132.     register DDXPointPtr ppt;        /* points to start copying from */
  133.     int            *pwidth;    /* list of number of bits to copy */
  134.     int            nspans;        /* number of scanlines to copy */
  135. #ifdef X11R4
  136.     unsigned int    *pdstStart;    /* where to put the bits */
  137. #endif
  138. {
  139.     static void        qdGSPixFull();
  140.     unsigned int *    pret;
  141.     int x, y;
  142. #if NPLANES==24
  143.     24-plane support has been removed
  144. #else
  145.     DDXPointPtr          pptInit;
  146.     int                  *pwidthInit;
  147.     int                  i;
  148. #endif
  149.     if ( pDrawable->type == UNDRAWABLE_WINDOW)
  150. #ifdef X11R4
  151.     {
  152.         pdstStart = (unsigned int *)NULL;
  153.         return ;
  154.     }
  155. #else
  156.     return (unsigned int *)NULL;
  157. #endif
  158.     if ( pDrawable->depth == 1 && pDrawable->type == DRAWABLE_PIXMAP) {
  159.     QDPixPtr pix = (QDPixPtr)pDrawable;
  160.     if (QD_PIX_DATA(&pix->pixmap) == NULL) {
  161. #if 0
  162. #ifndef X11R4
  163.         x = QDPIX_X(pix);
  164.         y = QDPIX_Y(pix);
  165. #endif
  166.         int plane_mask = pix->planes;
  167.         register unsigned char *dst;
  168.         char *buf = (char*)ALLOCATE_LOCAL(wMax);
  169.         i = nspans * PixmapBytePad(wMax, 1);
  170. #ifdef X11R4
  171.             dst = (unsigned char *)pdstStart;
  172. #else
  173.         dst = (unsigned char *)Xalloc(i);
  174.         pret = (unsigned int*)dst;
  175. #endif
  176.         bzero(dst, i);
  177.         for (i = nspans; --i >= 0; ppt++, pwidth++) {
  178.         register int j;
  179. #ifdef X11R4
  180.         tlgetspan((WindowPtr)0, ppt->x, ppt->y, *pwidth, buf);
  181. #else
  182.         tlgetspan((WindowPtr)0, x + ppt->x, y + ppt->y, *pwidth, buf);
  183. #endif
  184.         for (j = *pwidth; --j >= 0; )
  185.             if (buf[j] & plane_mask) {
  186.             dst[j>>3] |= 1 << (j & 7);
  187.             }
  188.         dst += PixmapBytePad(*pwidth, 1);
  189.         }
  190.         DEALLOCATE_LOCAL(buf);
  191. #ifdef X11R4
  192.             return;
  193. #else
  194.         return pret;
  195. #endif
  196. #else   /* 1 */
  197.         extern int DebugDma;
  198.         int size = pix->pixmap.devKind * QDPIX_HEIGHT(&pix->pixmap);
  199.         QD_PIX_DATA(&pix->pixmap) = (pointer)Xalloc(size);
  200. #ifdef DEBUG
  201.         if (DebugDma > 0)
  202.         printf("[Copy pixmap 0x%x from offscreen]\n", pix);
  203. #endif
  204.         CopyPixmapFromOffscreen(pix, QD_PIX_DATA(&pix->pixmap));
  205. #endif /* #if 1 */
  206.     }
  207. #ifdef X11R4
  208.         x = QDPIX_X(pix);
  209.     y = QDPIX_Y(pix);
  210.     QDPIX_X(pix) = QDPIX_Y(pix) = 0;
  211.     mfbGetSpans( pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
  212.         QDPIX_X(pix) = x;
  213.     QDPIX_Y(pix) = y;
  214.     return;
  215. #else
  216.     return mfbGetSpans( pDrawable, wMax, ppt, pwidth, nspans);
  217. #endif
  218.     }
  219.  
  220.     pptInit = ppt;
  221.     pwidthInit = pwidth;
  222.  
  223.     /*
  224.      * It's a full depth Pixmap or a window.
  225.      * Use an upper bound for the number of bytes to allocate.
  226.      */
  227.     if ( pDrawable->depth == Nplanes)
  228. #ifdef X11R4
  229.         pret = pdstStart;
  230.     else
  231.     {
  232.         pdstStart = (unsigned int *)NULL;
  233.         return;
  234.     }
  235. #else
  236.     pret = (unsigned int *) Xalloc( wMax * nspans);
  237.     else
  238.     return (unsigned int *)NULL;
  239. #endif
  240.     if ( pDrawable->type == DRAWABLE_WINDOW)
  241.     {
  242.     int    ns;            /* span count */
  243.     u_char *  pr = (u_char *) pret;
  244.  
  245.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++)
  246.     {
  247.         /*
  248.          *  order these come back in: RGBRGB...
  249.          */
  250.         tlgetspan((WindowPtr) pDrawable, ppt->x, ppt->y,
  251.               *pwidth, pr);
  252.         pr += *pwidth;
  253.     }
  254. #ifndef X11R4
  255.     /*
  256.      * If the drawable is a window with some form of backing-store, consult
  257.      * the backing-store module to fetch any invalid spans from the window's
  258.      * backing-store. The pixmap is made into one long scanline and the
  259.      * backing-store module takes care of the rest. We do, however, have
  260.      * to tell the backing-store module exactly how wide each span is, padded
  261.      * to the correct boundary.
  262.      */
  263.     if (((WindowPtr)pDrawable)->backingStore != NotUseful)
  264.     {
  265.         QDPixRec pix[1];
  266.  
  267.         pix->pixmap.drawable.type = DRAWABLE_PIXMAP;
  268.         pix->pixmap.drawable.pScreen = pDrawable->pScreen;
  269.         pix->pixmap.drawable.depth = pDrawable->depth;
  270.         pix->pixmap.drawable.serialNumber = NEXT_SERIAL_NUMBER;
  271.         QDPIX_WIDTH(&pix->pixmap) = wMax;
  272.         QDPIX_HEIGHT(&pix->pixmap) = 1;
  273.         pix->pixmap.refcnt = 1;
  274.         QD_PIX_DATA(&pix->pixmap) = (unsigned char *) pret;
  275.         QDPIX_Y(pix) = NOTOFFSCREEN;
  276.         LockPixmap(pix);
  277.         miBSGetSpans(pDrawable, pix, wMax, pptInit, pwidthInit,
  278.              pwidth, nspans);
  279.         UnlockPixmap(pix);
  280.     }
  281. #endif
  282.     }
  283.     else if (QD_PIX_DATA((PixmapPtr)pDrawable) == NULL){ /*offscreen PIXMAP*/
  284.     int    ns;            /* span count */
  285.     u_char *  pr = (u_char *) pret;
  286.  
  287.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++)
  288.     {
  289.         /*
  290.          *  order these come back in: RGBRGB...
  291.          */
  292.         tlgetspan((WindowPtr)NULL,
  293. #ifdef X11R4
  294.               ppt->x, ppt->y,
  295. #else
  296.               ppt->x + QDPIX_X((QDPixPtr)pDrawable),
  297.               ppt->y + QDPIX_Y((QDPixPtr)pDrawable),
  298. #endif
  299.               *pwidth, pr);
  300.         pr += *pwidth;
  301.     }
  302.     }
  303.     else    /* DRAWABLE_PIXMAP */
  304.     {
  305.     tlCancelPixmap( (QDPixPtr)pDrawable);
  306.     qdGSPixFull( (PixmapPtr)pDrawable, wMax, ppt, pwidth, nspans, pret);
  307.     }
  308. #ifndef X11R4
  309.     return pret;
  310. #endif
  311. }
  312.  
  313. static void
  314. qdGSPixFull( pPix, wMax, ppt, pwidth, nspans, pret)
  315.     PixmapPtr        pPix;
  316.     int            wMax;        /* largest value of all *pwidths */
  317.     register DDXPointPtr ppt;        /* points to start copying from */
  318.     int            *pwidth;    /* list of number of bits to copy */
  319.     int            nspans;        /* number of scanlines to copy */
  320.     int *        pret;        /* return value */
  321. {
  322.     u_char *    ps = QD_PIX_DATA(pPix);
  323.     register u_char *    pd = (u_char *)pret;
  324.     int        ns;                /* span count */
  325.     register int    i;
  326.     register int    pixwidth = QDPIX_WIDTH(pPix);
  327.  
  328.  
  329.     for ( ns=0; ns<nspans; ns++, pwidth++, ppt++) {
  330. #if NPLANES==24
  331.     int skip = ppt->y*pixwidth + ppt->x;
  332.     register u_char *psr = ps + skip;                 /*red*/
  333.     register u_char *psg = ps+pixwidth*QDPIX_HEIGHT(pPix)+skip; /*green*/
  334.     register u_char *psb = ps+2*pixwidth*QDPIX_HEIGHT(pPix)+skip; /*blue*/
  335.     for ( i = *pwidth; --i >= 0; )
  336.     {
  337.         *pd++ = *psr++; 
  338.         *pd++ = *psg++; 
  339.         *pd++ = *psb++; 
  340.     }
  341. #else
  342.     bcopy(ps + ppt->y * pixwidth + ppt->x, pd, *pwidth);
  343.     pd += *pwidth;
  344. #endif
  345.     }
  346. }
  347. void
  348. qdSetSpansWin(pDraw, pGC, pPixels, pPoint, pWidth, n, fSorted)
  349.     DrawablePtr pDraw;
  350.     GC *pGC;
  351.     pointer pPixels;
  352.     DDXPointPtr pPoint;
  353.     int *pWidth;
  354.     int n;
  355.     int fSorted;
  356. {
  357.     int        ispan;  /* counts spans */
  358.     int        ipix;    /* indexes pPixels; knows about pixel size */
  359.  
  360.     if (pWidth[0] <= 0 || n <= 0)
  361.     return;
  362.  
  363.     for ( ispan = ipix = 0; ispan < n; ipix += pWidth[ispan++]*Nchannels) {
  364. #if NPLANES==24
  365.     /*
  366.      * convert from rgb, rgb, rgb to
  367.      * all red, all green, all blue for tlsetspan's convenience
  368.      */
  369.     unsigned char *    newpix;
  370.     int        j, off;
  371.     register int    isnf;    /* index to server-natural */
  372.  
  373.     if ( pWidth[ispan] <= 0)
  374.         continue;
  375.     newpix = (unsigned char *)
  376.         ALLOCATE_LOCAL(pWidth[ispan] * 3 * sizeof(unsigned char));
  377.     for (j=0, isnf=ipix; j<pWidth[ispan]; j++) {
  378.         for (off = 0; off < 3; off++) {
  379.         newpix[j+pWidth[ispan]*off] =
  380.             pPixels[isnf++];
  381.         }
  382.     }
  383.     tlsetspans(pDraw, pGC, newpix, &pPoint[ispan],
  384.            &pWidth[ispan], 1, 1);
  385.     DEALLOCATE_LOCAL(newpix);
  386. #else    /* NPLANES == 8 */
  387.     if ( pWidth[ispan] <= 0)
  388.         continue;
  389.     tlsetspans(pDraw, pGC, &pPixels[ipix], &pPoint[ispan],
  390.            &pWidth[ispan], 1, 1);
  391. #endif
  392.     }
  393. }
  394.  
  395. void
  396. qdSetSpansPix1(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  397.     QDPixPtr pPix;
  398.     GC *pGC;
  399.     pointer pPixels;
  400.     DDXPointPtr pPoint;
  401.     int *pWidth;
  402.     int n;
  403.     int fSorted;
  404. {
  405.     if (QD_PIX_DATA(&pPix->pixmap) == NULL) {
  406.     /* This code could be better, but it shouldn't be used much. */
  407.     PixmapRec    tempBMap;
  408.     SETUP_PIXMAP_AS_WINDOW((DrawablePtr)pPix, pGC);
  409.     pGC->fgPixel = Allplanes;
  410.     pGC->bgPixel = 0;
  411.     QDPIX_HEIGHT(&tempBMap) = 1;
  412.     for ( ; --n >= 0; pWidth++, pPoint++) {
  413.         int         ic;     /* clip rect index */
  414.         int    numRects = REGION_NUM_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  415.         register BoxPtr rects = REGION_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  416.         BoxPtr newRects;
  417.  
  418.         /* create a temporary bitmap and transplant pImage into it  */
  419.         QDPIX_WIDTH(&tempBMap) = *pWidth;
  420.         tempBMap.devKind = PixmapBytePad(QDPIX_WIDTH(&tempBMap), 1);
  421.         QD_PIX_DATA(&tempBMap) = pPixels;
  422.  
  423.         for ( ic=0; ic < numRects; ic++, rects++)
  424.         tlBitmapBichrome(pGC, &tempBMap, Allplanes, 0,
  425.                  pPoint->x + QDPIX_X(pPix),
  426.                  pPoint->y + QDPIX_Y(pPix),
  427.                  rects);
  428.         pPixels += tempBMap.devKind;
  429.     }
  430.     CLEANUP_PIXMAP_AS_WINDOW(pGC);
  431.     }
  432.     else {
  433.     CHECK_MOVED(pGC, &pPix->pixmap.drawable);
  434.     mfbSetSpans(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  435.     }
  436. }
  437.  
  438. void
  439. qdSetSpansPixN(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  440.     PixmapPtr pPix;
  441.     GC *pGC;
  442.     pointer pPixels;
  443.     DDXPointPtr pPoint;
  444.     int *pWidth;
  445.     int n;
  446.     int fSorted;
  447. {
  448.     int        ispan;  /* counts spans */
  449.     int        ipix;    /* indexes pPixels; knows about pixel size */
  450.     int        j;
  451.     int        ic;    /* clip rect index */
  452.     BoxPtr      pc = REGION_RECTS(QDGC_COMPOSITE_CLIP(pGC));
  453. #if NPLANES<24
  454.     int fast;
  455. #endif
  456.  
  457.     if (pWidth[0] <= 0 || n <= 0)
  458.     return;
  459.  
  460.     if (QD_PIX_DATA(pPix) == NULL) {
  461.     CHECK_MOVED(pGC, &pPix->drawable);
  462.     qdSetSpansWin(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  463.     return;
  464.     }
  465.  
  466.     tlCancelPixmap( pPix);
  467.     CHECK_MOVED(pGC, &pPix->drawable);
  468.  
  469. #if NPLANES<24
  470.     fast = pGC->alu == GXcopy && (pGC->planemask & Allplanes) == Allplanes;
  471. #endif
  472.     /* for each clipping rectangle */
  473.     for ( ic = REGION_NUM_RECTS(QDGC_COMPOSITE_CLIP(pGC)); --ic >= 0; pc++) {
  474.     /* for each scan */
  475.     for (ispan = ipix = 0; ispan < n; ipix += pWidth[ispan++]*Nchannels) {
  476.         unsigned char *psrc, *pdst;
  477.         int x, y;
  478.         y = pPoint[ispan].y;
  479.         if (pc->y2 <= y || pc->y1 > y)
  480.         continue;
  481.         x = pPoint[ispan].x;
  482.         j = x+pWidth[ispan];
  483.         psrc = &pPixels[ipix];
  484.         if (x < pc->x1) {
  485.         psrc += Nchannels * (pc->x1 - x);
  486.         x = pc->x1;
  487.         }
  488.         if (j > pc->x2) j = pc->x2;
  489.         j -= x;
  490.         pdst = QD_PIX_DATA(pPix) + x + y * QDPIX_WIDTH(pPix);
  491. #if NPLANES != 24
  492.         if (fast) {
  493.         if (j > 0)
  494.             bcopy(psrc, pdst, j);
  495.         }
  496.         else
  497. #endif
  498.         while ( --j >= 0) { /* each pt */
  499.         if (x >= pc->x2) break;
  500.         DOPIXEL(psrc, pdst, pGC, QDPIX_WIDTH(pPix)*QDPIX_HEIGHT(pPix));
  501.         x++; psrc += Nchannels; pdst++;
  502.         }    /* for j (inc on scan) */
  503.     }    /* for ispan (scan) */
  504.     }
  505. }
  506.  
  507. #ifdef X11R4
  508. void
  509. qdSetSpansPix(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted)
  510.     PixmapPtr pPix;
  511.     GC *pGC;
  512.     pointer pPixels;
  513.     DDXPointPtr pPoint;
  514.     int *pWidth;
  515.     int n;
  516.     int fSorted;
  517. {
  518.     if (pPix->drawable.depth > 1)
  519.     qdSetSpansPixN(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  520.     else
  521.     qdSetSpansPix1(pPix, pGC, pPixels, pPoint, pWidth, n, fSorted);
  522. }
  523. #endif
  524.  
  525.  
  526. /*
  527.  * FillSpans cases
  528.  */
  529.  
  530. /*
  531.  * Hack arg list and call qdFillBoxesOddSize.
  532.  * In addition to having to duplicate code, it wins because the
  533.  * region routines called by the primitive rect fill routines
  534.  * can coalesce (thin) spans to larger boxes.
  535.  */
  536. void
  537. qdWinFSOddSize( pDraw, pGC, nInit, pptInit, pwidthInit, fSorted)
  538.     DrawablePtr    pDraw;
  539.     GC        *pGC;
  540.     int        nInit;
  541.     DDXPointPtr    pptInit;
  542.     int        *pwidthInit;
  543.     int        fSorted;
  544. {
  545.     BoxPtr    pdestboxes;
  546.     register BoxPtr    pbox;
  547.     int        nr;
  548.  
  549.     pdestboxes = pbox = (BoxPtr) ALLOCATE_LOCAL( nInit*sizeof(BoxRec));
  550.     for (nr = nInit; --nr >= 0; pbox++, pptInit++, pwidthInit++)
  551.     {
  552.     pbox->x1 = pptInit->x;
  553.     pbox->x2 = pptInit->x + *pwidthInit;
  554.     pbox->y1 = pptInit->y;
  555.     pbox->y2 = pptInit->y + 1;
  556.     }
  557.     qdPolyFillBoxesOddSize( pDraw, pGC, nInit, pdestboxes);
  558.     DEALLOCATE_LOCAL(pdestboxes);
  559. }
  560.  
  561. #define    CLIPSPANS \
  562.     register DDXPointPtr    ppt; \
  563.     register int *        pwidth; \
  564.     DDXPointPtr    ppt0; \
  565.     int *    pwidth0; \
  566.     int        n; \
  567.     n = nInit * miFindMaxBand(QDGC_COMPOSITE_CLIP(pGC));\
  568.     if ( n == 0) \
  569.     return; \
  570.     pwidth0 = pwidth = (int *)ALLOCATE_LOCAL( n * sizeof(int)); \
  571.     ppt0 = ppt = (DDXPointRec *)ALLOCATE_LOCAL( n * sizeof(DDXPointRec)); \
  572.     if ( !ppt || !pwidth) \
  573.     FatalError("alloca failed in qd FillSpans.\n"); \
  574.     n = miClipSpans(QDGC_COMPOSITE_CLIP(pGC), \
  575.     pptInit, pwidthInit, nInit, ppt, pwidth, fSorted)
  576.  
  577. #define CLIPSPANS_FREE \
  578.      DEALLOCATE_LOCAL(ppt0); DEALLOCATE_LOCAL(pwidth0)
  579.  
  580. #define CALL_SPAN_WITH_DUMMY(FUNC) \
  581.     /* make dummy window and use that as the drawable */\
  582.     SETUP_PIXMAP_AS_WINDOW(&pPix->drawable, pGC);    \
  583.     CHECK_MOVED(pGC, &pPix->drawable);            \
  584.     FUNC(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);\
  585.     CLEANUP_PIXMAP_AS_WINDOW(pGC);
  586.  
  587. void
  588. qdFSPixSolid(pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  589.     PixmapPtr    pPix;
  590.     GC        *pGC;
  591.     int        nInit;
  592.     DDXPointPtr    pptInit;
  593.     int        *pwidthInit;
  594.     int        fSorted;
  595. {
  596.     tlSinglePixmap( pPix);
  597.     if (QD_PIX_DATA(pPix) == NULL) {
  598.     CALL_SPAN_WITH_DUMMY(tlSolidSpans);
  599.     return;
  600.     }
  601.     CHECK_MOVED(pGC, &pPix->drawable);
  602.     if (pPix->drawable.depth == 1) {
  603.     void (*func)();
  604.     extern void mfbBlackSolidFS(), mfbWhiteSolidFS(), 
  605.         mfbInvertSolidFS();
  606. #ifdef X11R4
  607.     switch (mfbReduceRop(pGC->alu, pGC->fgPixel)) {
  608. #else
  609.     switch (ReduceRop(pGC->alu, pGC->fgPixel)) {
  610. #endif
  611.       case GXclear:    func = mfbBlackSolidFS; break;
  612.       case GXset:    func = mfbWhiteSolidFS; break;
  613.       case GXnoop:    func = NoopDDA; break;
  614.       case GXinvert:func = mfbInvertSolidFS; break;
  615.     }
  616.     (*func)(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  617.     }
  618.     else {
  619.     CLIPSPANS;
  620. #if NPLANES<24
  621.         if (pGC->alu == GXcopy && (pGC->planemask & Allplanes) == Allplanes) {
  622.         register long fg;
  623.         fg = pGC->fgPixel;
  624.         fg = (fg << 8) | fg;
  625.         fg = (fg << 16) | fg;
  626.         for ( ; --n >= 0; ppt++) {
  627.         register unsigned char *pdst =
  628.             QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  629.         register int w = *pwidth++;
  630.         int alDst = (int)pdst & 3;
  631.         /* simplified algorithm from cfbsp.c */
  632.         if (alDst + w <= 4) /* all bits inside same lonword */
  633.             while ( --w >= 0) *pdst++ = fg;
  634.         else {
  635.             if (alDst) {
  636.             /* word-align destination */
  637.             alDst = 4 - alDst;
  638.             w -= alDst;
  639.             while (--alDst >= 0) *pdst++ = fg;
  640.             }
  641.             /* loop over longwords */
  642.             alDst = w & 3;
  643.             w >>= 2;
  644.             while (--w >= 0)
  645.             *(long*)pdst++ = fg;
  646.             /* Do ragged right bytes. */
  647.             w = alDst;
  648.             while (--w >= 0) *pdst++ = fg;
  649.         }
  650.         }
  651.         }
  652.         else
  653. #endif
  654.         for ( ; n > 0; n--, pwidth++, ppt++) {
  655.         unsigned char *pdst =
  656.             QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  657.         for ( ; *pwidth; (*pwidth)--, pdst++)
  658.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  659.             QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  660.         }
  661.     CLIPSPANS_FREE;
  662.     }
  663. }
  664.  
  665. void
  666. qdFSPixTiled(pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  667.     PixmapPtr    pPix;
  668.     GC        *pGC;
  669.     int        nInit;
  670.     DDXPointPtr    pptInit;
  671.     int        *pwidthInit;
  672.     int        fSorted;
  673. {
  674.     register int    tbase, tinc, tbit;
  675.     unsigned long    scratch;
  676.     CLIPSPANS;
  677.  
  678.     tlSinglePixmap( pPix);
  679.     if (QD_PIX_DATA(pPix) == NULL) {
  680.     void (*func)();
  681.     extern void tlTiledSpans();
  682. #ifdef X11R4
  683.     if (qdNaturalSizePixmap(pGC->tile.pixmap)) func = tlTiledSpans;
  684. #else
  685.     if (qdNaturalSizePixmap(pGC->tile)) func = tlTiledSpans;
  686. #endif
  687.     else func = qdWinFSOddSize;
  688.     { CALL_SPAN_WITH_DUMMY((*func)); }
  689.     return;
  690.     }
  691.     
  692.     CHECK_MOVED(pGC, &pPix->drawable);
  693.     if (pPix->drawable.depth == 1) {
  694.     tlCancelPixmap(pGC->stipple);
  695. #ifdef X11R4
  696.     if (QDPIX_WIDTH(pGC->tile.pixmap) == 32)
  697. #else
  698.     if (pGC->tile && QDPIX_WIDTH(pGC->tile) == 32)
  699. #endif
  700.         mfbTileFS(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  701.     else
  702.         mfbUnnaturalTileFS(pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  703.     } else {
  704.     CLIPSPANS;
  705. #ifdef DEBUG
  706. #ifdef X11R4
  707.     if (PIXDEPTH(pGC->tile.pixmap) < Nplanes)
  708. #else
  709.     if (PIXDEPTH(pGC->tile) < Nplanes)
  710. #endif
  711.         FatalError("tile is not full-depth pixmap\n");
  712. #endif
  713.     for ( ; n > 0; n--, ppt++, pwidth++) {
  714.         unsigned char *pdst =
  715.         QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  716. #ifdef X11R4
  717.         tbase = ((ppt->y) % QDPIX_HEIGHT(pGC->tile.pixmap))
  718.         * QPPADBYTES(QDPIX_WIDTH(pGC->tile.pixmap));
  719. #else
  720.         tbase = ((ppt->y) % QDPIX_HEIGHT(pGC->tile))
  721.         * QPPADBYTES(QDPIX_WIDTH(pGC->tile));
  722. #endif
  723.         for ( ; *pwidth > 0; (ppt->x)++, *(pwidth)--, pdst++) {
  724. #ifdef X11R4
  725.         tinc = tbase + (ppt->x) % QDPIX_WIDTH(pGC->tile.pixmap);
  726.         ZCOPY(QD_PIX_DATA(pGC->tile.pixmap) + tinc, &scratch,
  727.           QDPIX_WIDTH(pGC->tile.pixmap) * QDPIX_HEIGHT(pGC->tile), 1);
  728. #else
  729.         tinc = tbase + (ppt->x) % QDPIX_WIDTH(pGC->tile);
  730.         ZCOPY(QD_PIX_DATA(pGC->tile) + tinc, &scratch,
  731.               QDPIX_WIDTH(pGC->tile) * QDPIX_HEIGHT(pGC->tile), 1);
  732. #endif
  733.         DOPIXEL(&scratch, pdst, pGC,
  734.             QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  735.         }
  736.     }
  737.     CLIPSPANS_FREE;
  738.     }
  739. }
  740.  
  741. void
  742. qdFSPixStippleorOpaqueStip( pPix, pGC, nInit, pptInit, pwidthInit, fSorted)
  743.     PixmapPtr    pPix;
  744.     GC        *pGC;
  745.     int        nInit;
  746.     DDXPointPtr    pptInit;
  747.     int        *pwidthInit;
  748.     int        fSorted;
  749. {
  750.     int    tbase;    /* address of first byte in a stipple row */
  751.     int    tinc;    /* byte address within a stipple row */
  752.     int    tbit;    /* bit address within a stipple byte */
  753.  
  754.     tlSinglePixmap( pPix);
  755.     if (QD_PIX_DATA(pPix) == NULL) {
  756.     void (*func)();
  757.     extern void tlStipSpans(), tlOpStipSpans();
  758.     if (!qdNaturalSizePixmap(pGC->stipple))
  759.         func = qdWinFSOddSize;
  760.     else if (pGC->fillStyle == FillStippled)
  761.         func = tlStipSpans;
  762.     else
  763.         func = tlOpStipSpans;
  764.     { CALL_SPAN_WITH_DUMMY((*func)); }
  765.     return;
  766.     }
  767.  
  768.     CHECK_MOVED(pGC, &pPix->drawable);
  769.     if (pPix->drawable.depth == 1) {
  770.     /* simplified simulation of stuff done by mfbValidateGC */
  771. #ifdef X11R4
  772.     int rop = mfbReduceRop(pGC->alu,pGC->fgPixel);
  773. #else
  774.     int rop = ReduceRop(pGC->alu,pGC->fgPixel);
  775. #endif
  776.     tlCancelPixmap(pGC->stipple);
  777.     if ( pGC->fillStyle == FillStippled) {
  778. #ifdef X11R4
  779.         ((mfbPrivGCPtr)pGC->devPrivates[mfbGCPrivateIndex].ptr)->rop = rop;
  780. #else
  781.         ((QDPrivGCPtr) pGC->devPriv)->mfb.rop = rop;
  782. #endif
  783.         mfbUnnaturalStippleFS( pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  784.     }
  785.     else {
  786.         extern int InverseAlu[16];
  787.         if (pGC->fgPixel == pGC->bgPixel) ;
  788.         else if (pGC->fgPixel) rop = pGC->alu;
  789.         else rop = InverseAlu[pGC->alu];
  790. #ifdef X11R4
  791.         ((mfbPrivGCPtr)pGC->devPrivates[mfbGCPrivateIndex].ptr)->ropOpStip = rop;
  792. #else
  793.         ((QDPrivGCPtr) pGC->devPriv)->mfb.ropOpStip = rop;
  794. #endif
  795.         mfbUnnaturalTileFS( pPix, pGC, nInit, pptInit, pwidthInit, fSorted);
  796.     }
  797.     return;
  798.     } else {
  799.     CLIPSPANS;
  800. #ifdef DEBUG
  801.     if (PIXDEPTH(pGC->stipple) != 1)
  802.         FatalError("stipple is not bitmap\n");
  803. #endif
  804.     for ( ; n > 0; n--, ppt++, pwidth++) {
  805.         unsigned char *pdst =
  806.         QD_PIX_DATA(pPix) + ppt->x + ppt->y * QDPIX_WIDTH(pPix);
  807.         tbase = UMOD(ppt->y-pGC->patOrg.y, QDPIX_HEIGHT(pGC->stipple))
  808.         * QPPADBYTES(QDPIX_WIDTH(pGC->stipple));
  809.         for ( ; *pwidth > 0; ppt->x++, (*pwidth)--, pdst++) {
  810.         tbit = ppt->x + pGC->patOrg.x;
  811.         tinc = tbase + UMOD(tbit, QDPIX_WIDTH(pGC->stipple)) / 8;
  812.         tbit &= 7;
  813.         if ( pGC->fillStyle == FillStippled) {
  814.             if ((QD_PIX_DATA(pGC->stipple)[tinc] >> tbit) & 1)
  815.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  816.                 QDPIX_WIDTH(pPix)*QDPIX_HEIGHT(pPix));
  817.         }
  818.         else {    /* FillOpaqueStippled */
  819.             if ((QD_PIX_DATA(pGC->stipple)[tinc] >> tbit) & 1)
  820.             DOPIXEL(&pGC->fgPixel, pdst, pGC,
  821.                 QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  822.             else
  823.             DOPIXEL(&pGC->bgPixel, pdst, pGC,
  824.                 QDPIX_WIDTH(pPix) * QDPIX_HEIGHT(pPix));
  825.         }
  826.         }
  827.     }
  828.     CLIPSPANS_FREE;
  829.     }
  830. }
  831.